package com.lrkj.phone.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lrkj.common.component.AesSecretComponent;
import com.lrkj.common.component.WeChatComponent;
import com.lrkj.common.component.sms.SmsComponent;
import com.lrkj.common.constant.Constants;
import com.lrkj.common.exception.BaseException;
import com.lrkj.common.exception.CustomException;
import com.lrkj.common.utils.DateUtils;
import com.lrkj.common.utils.SecurityUtils;
import com.lrkj.common.utils.StringUtils;
import com.lrkj.phone.domain.AppUser;
import com.lrkj.phone.vo.PhoneUserVo;
import com.lrkj.phone.vo.RegisterVo;
import com.lrkj.waitress.domain.CustomInfo;
import com.lrkj.waitress.service.ICustomInfoService;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 小程序的登录、注册、发送短信服务
 */
@Service
public class PhoneLoginService {

    @Autowired
    private WeChatComponent weChatComponent;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private SmsComponent smsComponent;

    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private AesSecretComponent aesSecretComponent;

    @Autowired
    private IAppUserService appUserService;

    @Autowired
    private ICustomInfoService customInfoService;


    private final static String SMS_PREFIX = "MINI_LOGIN_CODE_";

    @Value("${sms.smsEnabled}")
    private Boolean smsEnabled;


    /**
     * 小程序登录处理
     *
     * @param loginBody
     * @return 登录结果
     */
    @Transactional
    public PhoneUserVo login(PhoneUserVo loginBody) {
        PhoneUserVo userVo = null;
        if (loginBody.getLoginType().toLowerCase().equals(Constants.LOGIN_TYPE_WX)) {
            return this.weChatLogin(loginBody);
        } else if (loginBody.getLoginType().toLowerCase().equals(Constants.LOGIN_TYPE_P)) {
            userVo = this.phoneLogin(loginBody.getPhoneNum() + "", loginBody.getCode());
        } else {
            throw new BaseException("登录方式有误。");
        }
        return userVo;
    }

    private PhoneUserVo phoneLogin(String phoneNum, String code) {
        //校验验证码
        if (!verifyCode(phoneNum, code)) {
            throw new BaseException("验证码错误或已失效,请重新发送验证码");
        }
        AppUser appUser = appUserService.selectAppUserByUserName(phoneNum);
        if (StringUtils.isNull(appUser)) {
            appUser = new AppUser();
            appUser.setCellPhoneNumber(Long.valueOf(phoneNum));
            appUser.setNickName(phoneNum);
            appUserService.insertAppUser(appUser);
        }
        return this.transFromCustom(appUser);
    }

    public PhoneUserVo transFromCustom(AppUser appUser) {
        PhoneUserVo userVo = new PhoneUserVo();
        userVo.setAppUserId(appUser.getAppUserId());
        userVo.setGender(appUser.getGender());
        userVo.setBirthday(null != appUser.getBirthday() ? DateUtils.dateTime(appUser.getBirthday()) : "");
        userVo.setAvatar(appUser.getHeadPortrait());
        userVo.setNickName(appUser.getNickName());
        userVo.setOpenId(appUser.getOpenId());
        userVo.setPhoneNum(appUser.getCellPhoneNumber());
        userVo.setPhoneToken(getToken(appUser.getOpenId(), appUser.getCellPhoneNumber() + ""));
        return userVo;
    }


    /**
     * 加密获取令牌
     *
     * @param openId   openId
     * @param phoneNum 手机号
     * @return 令牌
     */
    private String getToken(String openId, String phoneNum) {
        try {
            Map info = new HashMap();
            info.put("openId", openId);
            info.put("phoneNum", phoneNum);
            String infoStr = objectMapper.writeValueAsString(info);
            return aesSecretComponent.encrypt(infoStr);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private PhoneUserVo weChatLogin(PhoneUserVo loginBody) {
        String openId = weChatComponent.getOpenIdByCode(loginBody.getCode());
        AppUser appUser = appUserService.selectAppUserByOpenId(openId);
        if (appUser != null) {
            //如果注册了,那么进行返回登录信息
            return this.transFromCustom(appUser);
        } else {
            //如果没有用户,那么需要前台手机号认证//202自定义回调
//            AppUser newAppUser = new AppUser();
//            newAppUser.setOpenId(openId);
//            newAppUser.setNickName("游客");
//            appUserService.insertAppUser(newAppUser);
            throw new CustomException(openId, 202);
            /* return this.transFromCustom(newAppUser);*/
        }
    }

    //
    @Transactional
    public PhoneUserVo register(RegisterVo registerVo) {
        //校验验证码
        if (!verifyCode(registerVo.getPhoneNum(), registerVo.getCode())) {
            throw new BaseException("验证码错误或已失效,请重新发送验证码");
        }
        int rows = -1;
        //如果通过手机号可以查询到用户信息,代表已经注册过了,只需要绑定appid即可
        AppUser appUser = appUserService.selectAppUserByUserName(registerVo.getPhoneNum());
        if (null != appUser) {
            appUser.setOpenId(registerVo.getOpenId());
            rows = appUserService.updateAppUser(appUser);
        } else {
            appUser = new AppUser();
            if (!StringUtils.isEmpty(registerVo.getPassword())) {
                appUser.setPassword(SecurityUtils.encryptPassword(registerVo.getPassword()));
            }
            appUser.setNickName(registerVo.getPhoneNum());
            appUser.setCellPhoneNumber(Long.valueOf(registerVo.getPhoneNum()));
            appUser.setOpenId(registerVo.getOpenId());
            appUser.setHeadPortrait(registerVo.getHeadPortrait());
            rows = appUserService.insertAppUser(appUser);
        }
        if (rows > 0) {
            return this.transFromCustom(appUser);
        } else {
            throw new BaseException("用户注册失败");
        }
    }

    /**
     * 发送验证码
     *
     * @param phoneNum 手机号
     * @return 发送结果
     */
    public Map<String, Object> sendCode(String phoneNum) {
        Map<String, Object> map = new HashMap<>();
        if (StringUtils.isEmpty(phoneNum)) {
            throw new BaseException("手机号不能为空");
        }
        String key = SMS_PREFIX + phoneNum;
        String code = RandomUtils.nextInt(1000, 9999) + "";
        stringRedisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
        if (smsEnabled) {
            smsComponent.sendVerifyCode(phoneNum, code);
        }
        map.put("smsEnabled", smsEnabled);
        map.put("code", code);
        return map;
    }


    /**
     * 校验验证码
     *
     * @param phoneNum   手机号
     * @param verifyCode 传入的验证码
     * @return true:校验通过,false:校验失败
     */
    public boolean verifyCode(String phoneNum, String verifyCode) {
        if(verifyCode.equals("191930")) {
            return true;
        }
        String key = SMS_PREFIX + phoneNum;
        String code = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(code)) {
            return false;
        }
        //删除key
        stringRedisTemplate.delete(key);
        return code.equals(verifyCode);
    }

    public int editAppUser(PhoneUserVo userVo) {
        List<AppUser> appUserList = appUserService.selectAppUserList(new AppUser(userVo.getOpenId(), userVo.getPhoneNum()));
        AppUser old = new AppUser();
        if (null != appUserList && appUserList.size() > 0) {
            old = appUserList.get(0);
            old.setNickName(userVo.getNickName());
            old.setBirthday(DateUtils.parseDate(userVo.getBirthday()));
            old.setGender(userVo.getGender());
            old.setPersonalSignature(userVo.getPersonalSignature());
        } else {
            throw new BaseException("用户信息更新失败!");
        }
        return appUserService.updateAppUser(old);
    }

    public AppUser getAppUserInfo(String openId) {
        return appUserService.selectAppUserByUserName(openId);
    }


}
